//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This is a sample for BCGControlBar Library Professional Edition
// Copyright (C) 1998-2016 BCGSoft Ltd.
// All rights reserved.
//
// This source code can be used, distributed or modified
// only under terms and conditions 
// of the accompanying license agreement.
//*******************************************************************************
//
// ChartFormulaTrendView.cpp : implementation file
//

#include "stdafx.h"
#include "bcgpchartexample.h"
#include "ChartFormulaTrendView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

class CMyFormula : public CBCGPChartTrendFormula
{
	DECLARE_DYNCREATE(CMyFormula)

	virtual void CalculateTrendCoefficients();
	virtual BOOL OnCalculateYValue(double dblXVal, CBCGPChartValue& dblYVal);
	virtual CString GetFormulaText() const;
};

IMPLEMENT_DYNCREATE(CMyFormula, CBCGPChartTrendFormula)

void CMyFormula::CalculateTrendCoefficients()
{
	ASSERT_VALID(this);

	CBCGPChartSeries* pSeries = GetInputSeriesAt(0);
	if (pSeries == NULL)
	{
		return;
	}

	ASSERT_VALID(pSeries);

	m_arCoef.RemoveAll();

	const int nDPCount = pSeries->GetDataPointCount();
	if (nDPCount == 0)
	{
		return;
	}

	double dblMinY = INT_MAX;
	double dblMaxY = 0;
	double dblSumY = 0;

	for (int i = 0; i < nDPCount; i++)
	{
		double dblY = pSeries->GetDataPointValue(i, CBCGPChartData::CI_Y);

		dblMinY = min(dblMinY, dblY);
		dblMaxY = max(dblMaxY, dblY);

		dblSumY += dblY;
	}

	if (dblSumY == 0.)
	{
		return;
	}

	m_arCoef.Add((dblMaxY - dblSumY) / dblSumY);
	m_arCoef.Add((dblSumY - dblMinY) / dblSumY);
}

BOOL CMyFormula::OnCalculateYValue(double dblXVal, CBCGPChartValue& dblYVal)
{
	if (m_arCoef.GetSize() == 0)
	{
		return FALSE;
	}

	double dblCoef0 = m_arCoef.GetSize() >= 1 ? m_arCoef[0] : 0;
	double dblCoef1 = m_arCoef.GetSize() >= 2 ? m_arCoef[1] : 0;

	dblYVal = dblCoef1 * dblXVal + dblCoef0;

	return TRUE;
}

CString CMyFormula::GetFormulaText() const
{
	CString strFormula;

	if (m_arCoef.GetSize() > 0)
	{
		double dblCoef0 = m_arCoef.GetSize() >= 1 ? m_arCoef[0] : 0;
		double dblCoef1 = m_arCoef.GetSize() >= 2 ? m_arCoef[1] : 0;

		strFormula.Format(_T("Y = %.2g * X %c %.2g"), dblCoef1, (dblCoef0 < 0 ? _T('-') : _T('+')), fabs(dblCoef0));
	}

	return strFormula;
}

/////////////////////////////////////////////////////////////////////////////
// CChartFormulaTrendView

IMPLEMENT_DYNCREATE(CChartFormulaTrendView, CBCGPChartExampleView)

CChartFormulaTrendView::CChartFormulaTrendView()
	: CBCGPChartExampleView(CChartFormulaTrendView::IDD),
	m_brText(CBCGPColor::Brown),
	m_brBorder(CBCGPColor::Goldenrod),
	m_brFill(CBCGPColor::LightYellow, .7)
{
	//{{AFX_DATA_INIT(CChartFormulaTrendView)
	m_nIsCustomFormula = 0;
	m_nFormulaType = 0;
	m_nPolOrder = 2;
	m_bShowFormulaText = TRUE;
	//}}AFX_DATA_INIT
}

CChartFormulaTrendView::~CChartFormulaTrendView()
{
}

void CChartFormulaTrendView::DoDataExchange(CDataExchange* pDX)
{
	CBCGPChartExampleView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CChartFormulaTrendView)
	DDX_Control(pDX, IDC_POL_LABEL, m_wndPolLabel);
	DDX_Control(pDX, IDC_POL_ORDER, m_wndPolOrder);
	DDX_Control(pDX, IDC_FORMULA_TYPE, m_wndFormulaType);
	DDX_Control(pDX, IDC_CHART, m_wndChart);
	DDX_Radio(pDX, IDC_FORMULA_1, m_nIsCustomFormula);
	DDX_CBIndex(pDX, IDC_FORMULA_TYPE, m_nFormulaType);
	DDX_CBIndex(pDX, IDC_POL_ORDER, m_nPolOrder);
	DDX_Check(pDX, IDC_SHOW_FORMULA_TEXT, m_bShowFormulaText);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CChartFormulaTrendView, CBCGPChartExampleView)
	//{{AFX_MSG_MAP(CChartFormulaTrendView)
	ON_BN_CLICKED(IDC_FORMULA_1, OnUpdateChart)
	ON_BN_CLICKED(IDC_FORMULA_2, OnUpdateChart)
	ON_CBN_SELENDOK(IDC_FORMULA_TYPE, OnUpdateChart)
	ON_CBN_SELENDOK(IDC_POL_ORDER, OnUpdateChart)
	ON_BN_CLICKED(IDC_SHOW_FORMULA_TEXT, OnUpdateChart)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChartFormulaTrendView diagnostics

#ifdef _DEBUG
void CChartFormulaTrendView::AssertValid() const
{
	CBCGPChartExampleView::AssertValid();
}

void CChartFormulaTrendView::Dump(CDumpContext& dc) const
{
	CBCGPChartExampleView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CChartFormulaTrendView message handlers

void CChartFormulaTrendView::OnInitialUpdate() 
{
	CBCGPChartExampleView::OnInitialUpdate();
	
	if (m_bIsReady)
	{
		return;
	}

	m_bIsReady = TRUE;

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	pChart->ShowDataMarkers();
	pChart->ShowDataLabels();

	CBCGPChartSeries* pSeries = pChart->CreateSeries(_T("Input Series"));
	pSeries->SetCurveType (BCGPChartFormatSeries::CCT_SPLINE);

	pSeries->AddDataPoint(4.);
	pSeries->AddDataPoint(2.);
	pSeries->AddDataPoint(2.5);
	pSeries->AddDataPoint(3.);
	pSeries->AddDataPoint(3.5);
	pSeries->AddDataPoint(5.);
	pSeries->AddDataPoint(6.);
	pSeries->AddDataPoint(4.);

	pSeries->SetBackroundOrder(TRUE);

	CBCGPChartSeries* pSeriesResult = pChart->CreateSeries(_T("Trend Line"));
	pSeriesResult->SetCurveType (BCGPChartFormatSeries::CCT_SPLINE_HERMITE);

	pChart->SetLegendPosition(BCGPChartLayout::LP_TOP);

	SetDefaultLineWidth();
	OnUpdateChart();
}

void CChartFormulaTrendView::OnUpdateChart() 
{
	UpdateData();

	const BOOL bIsPolType = (m_nFormulaType == 3);

	m_wndFormulaType.EnableWindow(m_nIsCustomFormula == 0);
	m_wndPolLabel.EnableWindow(m_nIsCustomFormula == 0 && bIsPolType);
	m_wndPolOrder.EnableWindow(m_nIsCustomFormula == 0 && bIsPolType);
	
	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	pChart->RemoveAllChartObjects();

	CBCGPChartSeries* pSeriesResult = pChart->GetSeries(1);
	ASSERT_VALID(pSeriesResult);

	if (m_nIsCustomFormula == 0)
	{
		CBCGPChartTrendFormula formula((CBCGPChartTrendFormula::TrendLineType)m_nFormulaType);
		formula.SetInputSeries(pChart->GetSeries(0));
		formula.SetPolynomialTrendOrder(m_nPolOrder + 2);

		pSeriesResult->SetFormula(formula);
	}
	else
	{
		CMyFormula formula;
		formula.SetInputSeries(pChart->GetSeries(0));

		pSeriesResult->SetFormula(formula);
	}

	if (m_bShowFormulaText)
	{
		CString strAnnotation;
		strAnnotation.Format(_T("Chart Formula:\n%s"), 
			((CBCGPChartTrendFormula*)pSeriesResult->GetFormula())->GetFormulaText());

		CBCGPChartTextObject* pAnnotation = new CBCGPChartTextObject(
			pChart, strAnnotation, 1, 1.5, m_brText, m_brFill, m_brBorder);

		pAnnotation->SetShadow();
		pAnnotation->SetRoundedShape();

		pChart->AddChartObject(pAnnotation);
	}

	OnChartAnimation();
}
